package com.simple.orm.agreement.process;

import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * 此接口的实现类，应该将字节数组，转换成目标对象
 *
 * @param <T> 目标对象的类型
 */
public interface ReadProcess<T> extends Closeable {

    /**
     * 将字节数组转换成目标对象
     *
     * @param data 字节数组
     * @param b true表示解析的包，前四个字节是包的有效总长度，false表示不解析总包长度
     * @return java可使用的目标对象
     */
    T readFrom(byte[] data, boolean b) throws IOException;

    /**
     * 实例化对象
     *
     * @param tClass 被实例化的对象的类对象
     * @return 实例化的对象
     */
    default T instance(Class<T> tClass) {
        Constructor<T>[] constructors = (Constructor<T>[]) tClass.getDeclaredConstructors();
        for (Constructor<T> constructor : constructors) {
            if (constructor.getParameterCount() > 0) continue;
            boolean accessible = constructor.isAccessible();
            try {
                return constructor.newInstance();
            } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            } finally {
                constructor.setAccessible(accessible);
            }
        }
        throw new IllegalArgumentException("找不到无参构造方法，无法实例化目标");
    }

    /**
     * 获取已注册的描述事件处理器，默认为null
     *
     * @return 描述事件处理器
     */
    DescribeEvent getDescribeEvent();

    /**
     * 注册描述事件处理器
     *
     * @param describeEvent 描述事件处理器
     */
    void setDescribeEvent(DescribeEvent describeEvent);

    /**
     * 描述事件处理器
     */
    interface DescribeEvent {

        /**
         * 如果使用了注解com.simple.orm.agreement.annotation.Describe注解，则重写并且注册此对象，即可获取到描述事件
         *
         * @param describe 协议的名称
         */
        void event(String describe);
    }
}
